Skip to content

Authenticate sessionless tokens#306

Closed
MiauzGenau wants to merge 3 commits into
Flowpack:2.xfrom
MiauzGenau:bugfix/graphql-middleware-sessionless-authentication
Closed

Authenticate sessionless tokens#306
MiauzGenau wants to merge 3 commits into
Flowpack:2.xfrom
MiauzGenau:bugfix/graphql-middleware-sessionless-authentication

Conversation

@MiauzGenau

@MiauzGenau MiauzGenau commented Jul 17, 2026

Copy link
Copy Markdown

My attempt to resolve: #305

This change injects the AuthenticationManagerInterface via the GraphQLMiddlewareFactory and calls authenticate() after the simulated request is assigned.
AuthenticationRequiredException is caught deliberately:
Authentication is attempted, not required, so anonymous/token-based API access (as described in the README) keeps working and privilege targets decide authorization as before.

Tested with:
flowpack/media-ui: 2.0.4
flownative/openidconnect-neos: 0.4.0
flownative/neos-canto: 0.6.0

@pKallert
pKallert requested review from Sebobo and pKallert July 20, 2026 08:27
@Sebobo
Sebobo requested a review from bwaidelich July 21, 2026 16:02
@Sebobo

Sebobo commented Jul 21, 2026

Copy link
Copy Markdown
Member

@bwaidelich can you verify this change as I copied the security part from your own implementation back then.

@bwaidelich

Copy link
Copy Markdown
Contributor

Mh, the $simulateControllerObjectName hack should actually cover this case..
@MiauzGenau what value does this option have in your case? It should contain an action that requires the corresponding auth tokens to be authenticated

@bwaidelich bwaidelich self-assigned this Jul 21, 2026
@MiauzGenau

Copy link
Copy Markdown
Author

The $simulateControllerObjectName shows Flowpack\Media\Ui\Controller\MediaController correctly.
And $this->securityContext->isInitialized() is true, but a call to $this->securityContext->getAccount() returns null.

For neos-canto that means we get a 'authorization needed' redirect: https://github.com/flownative/neos-canto/blob/main/Classes/Service/CantoClient.php#L106

@bwaidelich

Copy link
Copy Markdown
Contributor

@MiauzGenau The corresponding auth tokens aren't active for this controller it seems, maybe you can debug Security\Context::isTokenActive() why that is. I assume, that there is a missing request pattern

@bwaidelich

Copy link
Copy Markdown
Contributor

And maybe you could post the (deducted, if needed) output of ./flow configuration:show --path Neos.Flow.security.authentication.providers?

@MiauzGenau

Copy link
Copy Markdown
Author

I will take a look, but also for your information, as mentioned in the issue: SetJwtCookieMiddleware(Flownative.OpenIdConnect.Client) seems to also have issues with this where it sets an empty auth cookie, which logs the user out. (Set-Cookie: flownative_oidc_jwt=; Expires=Thu, 01-Jan-1970...).

DEBUG Flownative.OpenIdConnect.Client OpenID Connect: No account is authenticated using the provider Neos.Neos:Backend, removing JWT cookie "flownative_oidc_jwt".

@MiauzGenau

Copy link
Copy Markdown
Author

Providers config looks like this ATM:

'Neos.Neos:Backend':
    requestPatterns:
        'Neos.Media.Browser:Controllers':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Neos\Media\Browser\Controller\.*'
        'Neos.Neos:BackendControllers':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Neos\Neos\Controller\.*'
        'Neos.Neos:ServiceControllers':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Neos\Neos\Service\.*'
        'Neos.Neos.Ui:BackendControllers':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Neos\Neos\Ui\Controller\.*'
        'Shel.Neos.Terminal:Commands':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Shel\Neos\Terminal\Controller\.*'
        'Shel.Neos.WorkspaceModule:Controller':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Shel\Neos\WorkspaceModule\Controller\.*'
        'Paessler.AnchorLink:Backend':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\AnchorLink\Controller\.*'
        'Yoast.YoastSeoForNeos:DataSources':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Yoast\YoastSeoForNeos\Controller\.*'
        'Flownative.Canto:AuthorizationController':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: Flownative\Canto\Controller\AuthorizationController
        'Paessler.PrtgRelease:Backend':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\PrtgRelease\Controller\.*'
        'Paessler.GlobalContent:SyncButtonController':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\GlobalContent\Controller\.*Controller'
        'Paessler.GlobalText:Backend':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\GlobalText\Controller\.*'
        'Paessler.SensorHub:Backend':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\SensorHub\Controller\.*'
        'Paessler.Tags:Backend':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\Tags\Controller\.*'
        'Paessler.UrlToBackend:Backend':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\UrlToBackend\Controller\.*'
        'Flowpack.Media.Ui:Controllers':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Flowpack\Media\Ui\Controller\.*'
        'Paessler.DeepL:Backend':
            pattern: ControllerObjectName
            patternOptions:
                controllerObjectNamePattern: 'Paessler\DeepL\Controller\.*'
    label: 'OpenID Connect'
    provider: Flownative\OpenIdConnect\Client\Authentication\OpenIdConnectProvider
    entryPoint: Flownative\OpenIdConnect\Client\Authentication\OpenIdConnectEntryPoint
    entryPointOptions:
        routeValues:
            '@package': Neos.Neos
            '@controller': Login
            '@action': index
            '@format': html
        serviceName: neos
        scope: 'profile email'
    providerOptions:
        accountIdentifierTokenValueName: name
        serviceName: neos
        addRolesFromExistingAccount: true
    token: Flownative\OpenIdConnect\Client\Authentication\OpenIdConnectToken

@bwaidelich

Copy link
Copy Markdown
Contributor

OK, the settings look fine for me..

SetJwtCookieMiddleware(Flownative.OpenIdConnect.Client) seems to also have issues with this where it sets an empty auth cookie [...]

Yes, it removes the cookie if no account is authenticated. But the problem is, that no account is authenticated, not that it removes the cookie :)

Maybe also debug https://github.com/flownative/flow-openidconnect-client/blob/main/Classes/Http/SetJwtCookieMiddleware.php#L88 – i.e. what's $providerName here and why is the request not authenticated?

It's quite tedious to debug Flow auth because there are so many moving parts. We can look at it together in a call if you wish to!

@MiauzGenau

Copy link
Copy Markdown
Author

Yes I see it the same, we are not authenticated, that is why I proposed this PR, which would authenticate the request.

Provider name is Neos.Neos:Backend, as we can see in the DEBUG log output I posted.

If it helps we can look at it in a call together : )

@bwaidelich

Copy link
Copy Markdown
Contributor

we are not authenticated, that is why I proposed this PR

Thanks for that, but the thing is: Flow should automatically authenticate required tokens if everything is configured correctly.
I'm not sure about potential side effects of manually triggering the authentication (again) at this point.

If it helps we can look at it in a call together : )

Well, I hope it helps you :)

@MiauzGenau

Copy link
Copy Markdown
Author

For request: /neos/graphql/media-assets
In the SetJwtCookieMiddleware, I get no account for provider Neos.Neos:Backend.
But it looks like something like this $this->securityContext->getAuthenticationTokens()["Neos.Neos:Backend"]->extractIdentityTokenFromRequest('flownative_oidc_jwt')) gives some information.
But getAccount() returns null, probably because getAuthenticationStatus() returns 4 (AUTHENTICATION_NEEDED).

@MiauzGenau

Copy link
Copy Markdown
Author

Looks like for the fix we could also use $this->authenticationManager->isAuthenticated(), since that also authenticates if $this->isAuthenticated === null, that might be the more robust way to get it to work.

@bwaidelich bwaidelich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still prefer to understand why authentication is not correctly triggered automatically, but this change probably doesn't do any harm so I'd be fine with it.

Thanks!

@MiauzGenau

Copy link
Copy Markdown
Author

I sadly do not know enough about the Neos authentication and how it should be triggered automatically.
Especially with security relevant changes it probably a good idea to understand them fully.
So if somebody has time to double check this/ fully understand it, that would be great : )

(We have no urgency for this, it only prevents us from updating.)

Thank you : )

@bwaidelich

Copy link
Copy Markdown
Contributor

@MiauzGenau are you on slack and open for a quick call so I can try to reproduce your setup?

@MiauzGenau

Copy link
Copy Markdown
Author

I have no slack.

@bwaidelich

Copy link
Copy Markdown
Contributor

@MiauzGenau OK, in order to reproduce your issue I would need to know your setup.. You could describe it or suggest any other way to establish a quick call if you're up for it

@MiauzGenau

MiauzGenau commented Jul 22, 2026

Copy link
Copy Markdown
Author

You would at least need a setup with https://github.com/flownative/openidconnect-neos (or something which uses a similar way to authenticate), on our end this requires a setup in Azure. Not sure how you can get a test setup working with that. (But I guess this would be the most important step to be able to reproduce it.)

(Then in our case we use https://github.com/flownative/neos-canto, which would require a connection to Canto, this is probably also not easy to reproduce. (I'm not sure if this is needed to reproduce the error.))

I'm happy to describe it in a call, but I never really had the use-case of having to setup a call outside the company.
Internally we use MS Teams. Sadly no clue how I would setup a call like this.

Feel free to point out how I can describe it in a better way : )

@bwaidelich

Copy link
Copy Markdown
Contributor

I was able to reproduce the issue by installing the flownative/openidconnect-neos package (with a local OIDC provider).
The actual bug comes from a missing policy for the MediaAPI, see #307 /cc @Sebobo

@MiauzGenau

Copy link
Copy Markdown
Author

I tested it and it seems to resolve the issue for me 👍

@MiauzGenau MiauzGenau closed this Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants